feat(ide-sync): add Kimi Code as supported IDE target - #683
Conversation
Adds Kimi Code (https://www.kimi-cli.com) to the IDE sync pipeline as a new target with format `kimi-skill`. Kimi consumes per-skill directories shaped as `<skill-id>/SKILL.md` and discovers them at the project Git root, so the transformer differs from the flat layouts used by Claude Code, Codex, Gemini, Cursor, and Antigravity. Changes - transformers/kimi.js: new transformer producing SKILL.md with YAML frontmatter, Activation Protocol directive, persona, Star Commands table, and the full raw agent definition. Includes: - skillId normalization (avoids `aios-aios-master` double prefix) - support for `preferredActivationAlias` - safe rendering of YAML array items that parse as objects (`- CRITICAL: x` was previously serialized as `[object Object]`) - index.js: register transformer, add `kimi` default target with `fallbackSources: ['.codex/agents']`, and write nested `<skill-id>/SKILL.md` paths during sync and validation expectation. - validator.js: walk markdown recursively so nested Kimi layouts are matched against expected files instead of being flagged as orphaned. - tests/ide-sync/kimi-transformer.test.js: covers skillId rules, preferredActivationAlias, [object Object] regression, Activation Protocol presence, and nested layout filenames (5/5 passing). Discovery contract Kimi resolves project root to the nearest `.git` ancestor, so the generated `.kimi/skills/` should live at that level (or be reachable via symlink). No changes to other IDE targets or behaviors. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📊 Coverage ReportCoverage report not available
Generated by PR Automation (Story 6.1) |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (18)
WalkthroughThis PR adds Kimi IDE support: config/schema entries for a new ChangesKimi IDE Transformer Infrastructure
Agent Skill Definitions
Sequence Diagram(s)sequenceDiagram
participant IdeSync
participant Transformer
participant FS
participant Validator
IdeSync->>Transformer: load transformer, transform(agentData)
Transformer->>FS: write <skill-id>/SKILL.md (nested)
IdeSync->>Validator: validateIdeSync request
Validator->>FS: walkSyncFiles(root) (recursive .md/.mdc)
Validator->>IdeSync: report expected vs discovered (orphan/drift/missing)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Add Kimi skill format and fallback source support to framework config schema - Cover skills-first IDE options in schema validation tests - Regenerate install manifest after schema update Co-Authored-By: OpenAI Codex <codex@openai.com>
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
.aiox-core/infrastructure/scripts/ide-sync/index.js (1)
34-34: ⚡ Quick winUse an absolute import for the new transformer require.
This new import adds a relative path in a JS file where the repo standard requires absolute imports.
Suggested fix
-const kimiTransformer = require('./transformers/kimi'); +const kimiTransformer = require(path.resolve(__dirname, 'transformers', 'kimi'));As per coding guidelines,
**/*.{js,jsx,ts,tsx}: Use absolute imports instead of relative imports in all code.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.aiox-core/infrastructure/scripts/ide-sync/index.js at line 34, The new relative require for the transformer (kimiTransformer via require('./transformers/kimi')) violates the repo rule to use absolute imports; update the import to use the repository's absolute module path (replace the './transformers/kimi' require with the project's absolute import for that transformer) so the codebase uses the same module-resolver/alias style as other imports and passes linting..aiox-core/infrastructure/scripts/ide-sync/validator.js (1)
140-158: 💤 Low valueOuter
try/catchwrappingwalkSyncFilesis dead code.
walkSyncFilesalready catches allreaddirSyncerrors internally and returns[]. The for-loop only performs Set lookups and array pushes, which cannot throw. The outercatch(line 155) will never be reached, and its comment"Ignore directory read errors"is misleading since those errors are already silenced inside the helper.🧹 Proposed cleanup
if (fs.existsSync(targetDir)) { - try { - const actualFiles = walkSyncFiles(targetDir, targetDir); - - for (const file of actualFiles) { - if (!expectedFilenames.has(file)) { - result.orphaned.push({ - filename: file, - path: path.join(targetDir, file), - }); - result.total.orphaned++; - } - } - } catch (error) { - // Ignore directory read errors + const actualFiles = walkSyncFiles(targetDir, targetDir); + for (const file of actualFiles) { + if (!expectedFilenames.has(file)) { + result.orphaned.push({ + filename: file, + path: path.join(targetDir, file), + }); + result.total.orphaned++; + } } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.aiox-core/infrastructure/scripts/ide-sync/validator.js around lines 140 - 158, The outer try/catch around the call to walkSyncFiles is dead code because walkSyncFiles already handles readdirSync errors and returns [], so remove the surrounding try/catch block and its misleading comment; simply call walkSyncFiles(targetDir, targetDir), iterate the returned actualFiles and perform the existing checks against expectedFilenames, pushing to result.orphaned and incrementing result.total.orphaned as before (leave walkSyncFiles, expectedFilenames, result.orphaned and result.total.orphaned references intact).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.aiox-core/infrastructure/scripts/ide-sync/index.js:
- Around line 208-216: The code currently blindly uses
transformer.getDirname(agent) to build skillDir and may allow path traversal;
fix by resolving and validating the dirname before joining: call
transformer.getDirname(agent) into a variable (e.g., dirname), compute
resolvedSkillDir = path.resolve(result.targetDir, dirname) (or use path.join
then path.resolve), verify that path.relative(path.resolve(result.targetDir),
resolvedSkillDir) does not start with '..' and that resolvedSkillDir starts with
path.resolve(result.targetDir) to ensure it stays inside the target tree, only
then set skillDir/resolvedSkillDir as the directory used for targetPath and call
fs.ensureDirSync (skip writing if validation fails or throw an error); keep the
same identifiers (transformer.getDirname, result.targetDir, skillDir,
targetPath, filename, options.dryRun, fs.ensureDirSync) so the change is easy to
locate.
In @.aiox-core/infrastructure/scripts/ide-sync/transformers/kimi.js:
- Around line 65-67: The generated fenced code block for the activation greeting
currently emits an untyped fence ("```${namedGreeting}```"), which triggers
MD040; update the template that renders the fenced block to include an explicit
language token (e.g., "text" or "markdown") before the newline so the fence
becomes "```text\n${namedGreeting}\n```" (locate the template where
namedGreeting is interpolated and add the language identifier to the opening
fence).
- Around line 133-136: buildCommandsTable currently only accepts array-shaped
catalogs and returns '' for object-shaped command maps; change the initial guard
to detect object maps (typeof commands === 'object' && !Array.isArray(commands))
and normalize them to an array (e.g., commands = Object.values(commands)) before
proceeding so the rest of buildCommandsTable can generate the table; ensure the
function still returns '' for null/undefined or empty arrays after
normalization.
In @.kimi/skills/aios-aiox-master/SKILL.md:
- Around line 19-21: The fenced code block containing "👑 Orion (Orchestrator)
ready. Let's orchestrate!" should include a language identifier to satisfy
MD040; update the triple-backtick fence to start with ```text (or another
explicit language) so it becomes ```text followed by the existing line and the
closing ``` to fix the lint warning.
- Around line 520-524: The markdown lines listing tasks contain bare starred
tokens (e.g., *create-epic, *create-prd, *draft, *create-story,
*validate-story-draft, *develop-story, *push, *create-pr, *release) which are
being parsed as emphasis; update each bare starred command by wrapping it in
inline code spans (backticks) so they become `*create-epic`, `*create-prd`,
`*draft`, `*create-story`, `*validate-story-draft`, `*develop-story`, `*push`,
`*create-pr`, `*release` (do this for every occurrence in the listed lines such
as the **Epic/PRD/spec work**, **Story creation**, **Story validation/backlog**,
**Implementation**, and **GitHub, PR, release, MCP** bullets).
In @.kimi/skills/aios-data-engineer/SKILL.md:
- Around line 33-65: The commands YAML block currently uses legacy single-key
objects (e.g., "- create-schema: Design database schema") so the Kimi
transformer emits "*undefined"; fix by converting each command entry in the
commands block to the structured form with explicit fields: "- name:
create-schema", "description: Design database schema", "visibility: full"
(ensure all agent-specific entries use name/description/visibility), or
alternatively update the Kimi transformer parsing code (the commands parsing
logic in the transformer) to detect single-key objects and normalize them into
{name, description, visibility:'full'} before downstream processing so legacy
formats are handled as a fallback.
---
Nitpick comments:
In @.aiox-core/infrastructure/scripts/ide-sync/index.js:
- Line 34: The new relative require for the transformer (kimiTransformer via
require('./transformers/kimi')) violates the repo rule to use absolute imports;
update the import to use the repository's absolute module path (replace the
'./transformers/kimi' require with the project's absolute import for that
transformer) so the codebase uses the same module-resolver/alias style as other
imports and passes linting.
In @.aiox-core/infrastructure/scripts/ide-sync/validator.js:
- Around line 140-158: The outer try/catch around the call to walkSyncFiles is
dead code because walkSyncFiles already handles readdirSync errors and returns
[], so remove the surrounding try/catch block and its misleading comment; simply
call walkSyncFiles(targetDir, targetDir), iterate the returned actualFiles and
perform the existing checks against expectedFilenames, pushing to
result.orphaned and incrementing result.total.orphaned as before (leave
walkSyncFiles, expectedFilenames, result.orphaned and result.total.orphaned
references intact).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ceaf308c-e129-4818-82d0-1f52c9118a73
📒 Files selected for processing (21)
.aiox-core/core-config.yaml.aiox-core/framework-config.yaml.aiox-core/infrastructure/scripts/ide-sync/README.md.aiox-core/infrastructure/scripts/ide-sync/index.js.aiox-core/infrastructure/scripts/ide-sync/transformers/kimi.js.aiox-core/infrastructure/scripts/ide-sync/validator.js.aiox-core/install-manifest.yaml.kimi/skills/aios-aiox-master/SKILL.md.kimi/skills/aios-analyst/SKILL.md.kimi/skills/aios-architect/SKILL.md.kimi/skills/aios-data-engineer/SKILL.md.kimi/skills/aios-dev/SKILL.md.kimi/skills/aios-devops/SKILL.md.kimi/skills/aios-pm/SKILL.md.kimi/skills/aios-po/SKILL.md.kimi/skills/aios-qa/SKILL.md.kimi/skills/aios-sm/SKILL.md.kimi/skills/aios-squad-creator/SKILL.md.kimi/skills/aios-ux-design-expert/SKILL.mdtests/ide-sync/kimi-transformer.test.jstests/ide-sync/validator.test.js
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/config/schema-validation.test.js (1)
72-77: 💤 Low valueOptional: guard
formatproperty access to produce a cleaner failure messageLine 76 chains directly into
targetSchema.properties.format.enum. Ifformatis ever absent from the schema properties, this throws aTypeErrorinstead of a descriptive Jest assertion failure, making the failure harder to diagnose. A one-line guard assertingformatexists first would give a cleantoHavePropertymessage instead of an unhandled crash.✨ Proposed optional guard
expect(targetSchema.properties).toHaveProperty('skillsPath'); expect(targetSchema.properties).toHaveProperty('fallbackSources'); + expect(targetSchema.properties).toHaveProperty('format'); expect(targetSchema.properties.format.enum).toContain('kimi-skill');🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/config/schema-validation.test.js` around lines 72 - 77, The test 'ide sync target schema accepts skills-first IDE target options' accesses targetSchema.properties.format.enum directly which can throw if 'format' is missing; add a guard assertion before that access by asserting targetSchema.properties hasOwnProperty 'format' (e.g., use expect(targetSchema.properties).toHaveProperty('format')) and then perform the existing expectation on targetSchema.properties.format.enum to ensure a clear Jest failure message if 'format' is absent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/config/schema-validation.test.js`:
- Around line 72-77: The test 'ide sync target schema accepts skills-first IDE
target options' accesses targetSchema.properties.format.enum directly which can
throw if 'format' is missing; add a guard assertion before that access by
asserting targetSchema.properties hasOwnProperty 'format' (e.g., use
expect(targetSchema.properties).toHaveProperty('format')) and then perform the
existing expectation on targetSchema.properties.format.enum to ensure a clear
Jest failure message if 'format' is absent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 155693c5-8862-4636-a812-8c1bb9ed4d56
📒 Files selected for processing (3)
.aiox-core/core/config/schemas/framework-config.schema.json.aiox-core/install-manifest.yamltests/config/schema-validation.test.js
✅ Files skipped from review due to trivial changes (1)
- .aiox-core/install-manifest.yaml
- Guard nested Kimi writes against target-directory escapes - Normalize object and legacy command catalogs before rendering - Regenerate Kimi skills with typed fences and escaped star commands - Clean redundant orphan validation wrapper and refresh manifest Co-Authored-By: OpenAI Codex <codex@openai.com>
Adds Kimi Code as a skills-first IDE sync target and hardens generated Kimi skill output after review. Validated locally with lint, typecheck, sync checks, manifest validation, targeted IDE-sync tests, schema test, and full Jest suite; GitHub CI checks passed on the final head commit before admin merge.
Supersedes #644.
Summary
main..kimi/skills/<skill-id>/SKILL.mdoutput, repo config entries, docs, generated Kimi skills, and install-manifest updates.design_rules, snake_case preferred alias coverage, and nested orphan detection.Validation
Notes
${...}fragments for the new transformer.Summary by CodeRabbit
New Features
Documentation
Tests